﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "StructureSlantedColumn.h"
#include "ColumnParameterBehavior.h"
#include "DbObjectUtils.h"
#include "GbmpBuiltInParameterDefinitionsNew.h"
#include "GbmpCalculatorBase.h"
#include "GcmpBuiltInParameterDefinitions.h"
#include "GmStructureDefaultElementParametersCustomizer.h"
#include "ICalculatorCollection.h"
#include "IDocument.h"
#include "IElementModelShape.h"
#include "IElementParameters.h"
#include "IElementParentReporter.h"
#include "IElementPosition.h"
#include "IElementStatus.h"
#include "IElementTransformationComponent.h"
#include "IExternalDataComponent.h"
#include "IFamily.h"
#include "IInstance.h"
#include "IInstanceType.h"
#include "ILine2d.h"
#include "IParameter.h"
#include "IParameterDefinitionLibrary.h"
#include "IParameterValueElementId.h"
#include "IPointArrayPlusHeightInstanceInput.h"
#include "IPositionCurve2d.h"
#include "IPositionTwoAssociatedPlanes.h"
#include "IRegenerator.h"
#include "IRegeneratorDataIdCreator.h"
#include "StructureColumnEndTypeBehavior.h"
#include "StructureColumnHeightParameterUpdater.h"
#include "StructureColumnInput.h"
#include "StructureGeneralParameterValidator.h"
#include "StructureInstanceCutterGRepComponent.h"
#include "StructureInstanceLevelUtils.h"
#include "IGeometryRelationshipComponent.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;
namespace gcmp
{
    class SlantedColumnAngleCalculator : public GbmpCalculatorBase
    {
        DECLARE_CALCULATOR(SlantedColumnAngleCalculator, IInstance)
    public:
        SlantedColumnAngleCalculator(IDocument* pDoc, const RegenDataId& outputDataId) : GbmpCalculatorBase(pDoc, outputDataId) {}
        virtual void ReportInputDataIds(std::vector<RegenDataId> & dataIds) const override;
        virtual void Execute() override;
    };

    void SlantedColumnAngleCalculator::ReportInputDataIds(std::vector<RegenDataId> & dataIds) const
    {
        const IElement* pElement = GetElement<IElement>();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pElement, L"计算器的目标对象为空",L"GDMPLab",L"2024-03-30");

        const IElementParameters* pElementParameters = pElement->GetElementParameters();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pElementParameters, L"参数行为为空",L"GDMPLab",L"2024-03-30");

        dataIds.push_back(pElementParameters->GetDriveParameterRdId());

        const IElementTransformationComponent* pElementPositionPoints = pElement->GetElementTransformationComponent();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pElementPositionPoints, L"pElementPositionPoints为空",L"GDMPLab",L"2024-03-30");

        dataIds.push_back(pElementPositionPoints->GetTransformedRdId(pElement->GetElementId()));
    }

    void SlantedColumnAngleCalculator::Execute()
    {
        IInstance* pElement = GetElement<IInstance>();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pElement, L"计算器的目标对象为空",L"GDMPLab",L"2024-03-30");

        IElementParameters* pElementParameters = pElement->GetElementParameters();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pElementParameters, L"参数行为为空",L"GDMPLab",L"2024-03-30");

        OwnerPtr<IParameter> heightParam = pElementParameters->GetParameterByUid(PARAMETER_UID(ColumnHeightBuiltInParameter));
        DBG_WARN_AND_RETURN_VOID_UNLESS(IParameter::IsValidParameter(heightParam), L"没有高度参数",L"GDMPLab",L"2024-03-30");

        double height = heightParam->GetValueAsDouble();
        const IElementPosition* posBehavior = pElement->GetElementPosition();
        DBG_WARN_AND_RETURN_VOID_UNLESS(posBehavior != nullptr, L"无效posBehavior",L"GDMPLab",L"2024-03-30");

        const IPositionGeometry* pGeometry = posBehavior->GetPositionGeometry();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pGeometry, L"定位对象为空",L"GDMPLab",L"2024-03-30");

        const IPositionCurve2d *pPosCurve2d = quick_cast<IPositionCurve2d>(pGeometry);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pPosCurve2d, L"二维定位线为空",L"GDMPLab",L"2024-03-30");

        //二维定位线
        const ILine2d *pLine2d = quick_cast<ILine2d>(pPosCurve2d->GetBaseCurve());
        Vector2d dir;
        if (pLine2d)
        {
            Vector2d startPt = pLine2d->GetStartPoint();
            Vector2d endPt = pLine2d->GetEndPoint();
            dir = endPt - startPt;
        }

        double angle = std::atan2(dir.Length(), height);
        OwnerPtr<IParameter> angleParam = pElementParameters->GetParameterByUid(PARAMETER_UID(ColumnAngleBuiltInParameter));
        DBG_WARN_AND_RETURN_VOID_UNLESS(IParameter::IsValidParameter(angleParam), L"没有角度参数",L"GDMPLab",L"2024-03-30");

        angleParam->SetValueAsDouble(angle);
        pElement->GetElementParameters()->SetParameter(angleParam.get());
    }
    IMPLEMENT_CALCULATOR_CREATOR(gcmp, SlantedColumnAngleCalculator);

    class StructureSlantedColumnElementParametersCustomizer : 
        public GmStructureDefaultElementParametersCustomizer
    {
        DBOBJECT_DATA_BEGIN(gcmp, StructureSlantedColumnElementParametersCustomizer, 
            gcmp::GmStructureDefaultElementParametersCustomizer, 
            D8DD4F02-C12D-47E2-8E65-3D00C156A1A8, gmstructure)
        DBOBJECT_DATA_END
    public:
        StructureSlantedColumnElementParametersCustomizer(IElement* pElement);

        virtual bool IsPresetParameter(const UniIdentity& paramDefUid) const override;

        virtual void FilterParameterValues(const UniIdentity& paramDefUid, 
            std::vector<OwnerPtr<IParameterValueStorage>>& values) const override;
    };
}

DBOBJECT_DATA_DEFINE(StructureSlantedColumnElementParametersCustomizer)
{
    SetOwnerElement(nullptr);
}

StructureSlantedColumnElementParametersCustomizer::StructureSlantedColumnElementParametersCustomizer(
    IElement* pElement) : GmStructureDefaultElementParametersCustomizer(pElement)
{
}

bool StructureSlantedColumnElementParametersCustomizer::IsPresetParameter(const UniIdentity& paramDefUid) const
{
    if (paramDefUid.HasSameValue(PARAMETER_DEF(ElementAssociatedLevelBuiltInParameter)->GetUid()) ||
        paramDefUid.HasSameValue(PARAMETER_UID(BuildingStoreyBuiltInParameter)) ||
        paramDefUid.HasSameValue(PARAMETER_DEF(TopAssociatedLevelBuiltInParameter)->GetUid()) ||
        paramDefUid.HasSameValue(PARAMETER_DEF(BottomOffsetBuiltInParameter)->GetUid()) ||
        paramDefUid.HasSameValue(PARAMETER_DEF(TopOffsetBuiltInParameter)->GetUid()) ||
        paramDefUid.HasSameValue(PARAMETER_DEF(ColumnHeightBuiltInParameter)->GetUid()) ||
        paramDefUid.HasSameValue(PARAMETER_DEF(ConcreteStrengthGradeBuiltInParameter)->GetUid())||
        paramDefUid.HasSameValue(PARAMETER_DEF(SectionRotateAngleBuiltInParameter)->GetUid()) ||
        paramDefUid.HasSameValue(PARAMETER_DEF(ColumnTopSectionType)->GetUid()) ||
        paramDefUid.HasSameValue(PARAMETER_DEF(ColumnBottomSectionType)->GetUid())
        )
    {
        return true;
    }

    return false;
}

void StructureSlantedColumnElementParametersCustomizer::FilterParameterValues(
    const UniIdentity& paramDefUid, std::vector<OwnerPtr<IParameterValueStorage>>& values) const
{
    // 柱的定位方式为底标高+顶标高或底标高+柱高，其默认顶标高为Invalid，默认下拉列表默认有“< 空 >”
    if (paramDefUid.HasSameValue(PARAMETER_UID(TopAssociatedLevelBuiltInParameter)))
    {
        values.push_back(IParameterValueElementId::Create(ElementId::InvalidID));
    }
}

DEFINE_STRUCTURE_INSTANCE_BASE_DATA_METHODS(StructureSlantedColumn, BaseData);

IMPLEMENT_REGEN_FUNCTIONS(gcmp, StructureSlantedColumn, TopSectionType)
IMPLEMENT_REGEN_FUNCTIONS(gcmp, StructureSlantedColumn, BottomSectionType)

DBOBJECT_DATA_DEFINE(StructureSlantedColumn)
{
    SetTopSectionType__(InstanceEndType::PerpendicularToAxis);  // 斜柱 顶部和底部截面样式默认值 垂直于轴线
    SetBottomSectionType__(InstanceEndType::PerpendicularToAxis);
}

IStructureSlantedColumn* StructureSlantedColumn::Create(const StructureColumnInput* pInput)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInput, L"pInput为空",L"GDMPLab",L"2024-03-30");

    IInstance* pInstance = StructureSlantedColumn::CreateSlantedColumn(pInput);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInstance, L"pInstance为空",L"GDMPLab",L"2024-03-30");

    IStructureSlantedColumn* pSlantedColumn = StructureSlantedColumn::Get(pInstance);

    {
        IElementParameters * pElementParameters = pInstance->GetElementParameters();
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pElementParameters, L"pInstance的参数行为为空？",L"GDMPLab",L"2024-03-30");
        pElementParameters->AddIndividualParameterOverride(NEW_AS_OWNER_PTR(NotModifiableColumnAngleBuiltInParameterOverride));
        pElementParameters->AddIndividualParameterOverride(NEW_AS_OWNER_PTR(GeneralHeightBuiltInParameterOverride, pInstance, PARAMETER_UID(ColumnHeightBuiltInParameter)));
    }

    // 定制扣减行为

    IGeometryRelationshipComponent* pGeometryRepCmpt = pInstance->GetGeometryRelationshipComponent();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pGeometryRepCmpt, L"pGeometryRepCmpt不能为空",L"GDMPLab",L"2024-03-30");
    pGeometryRepCmpt->SetCutterGraphicsElementShapeComponent(NEW_AS_OWNER_PTR(StructureInstanceCutterGRepComponent));

    return pSlantedColumn;
}

const StructureSlantedColumn *StructureSlantedColumn::Get(const IInstance *pInstance)
{
    DBG_WARN_AND_RETURN_UNLESS(pInstance, nullptr, L"pInstance为空",L"GDMPLab",L"2024-03-30");
    if (const IExternalDataComponent * pExternalDataComponent = pInstance->GetExternalDataComponent())
    {
        const IExternalData *pData = pExternalDataComponent->FindExternalData(StructureSlantedColumn::GetStaticClassSchema()->GetName());
        DBG_WARN_AND_RETURN_UNLESS(pData, nullptr, L"结构构件应该会有ExternalData",L"GDMPLab",L"2024-03-30");
        return quick_cast<StructureSlantedColumn>(pData);
    }
    return nullptr;
}

StructureSlantedColumn *StructureSlantedColumn::Get(IInstance *pInstance)
{
    DBG_WARN_AND_RETURN_UNLESS(pInstance, nullptr, L"pInstance为空",L"GDMPLab",L"2024-03-30");
    if (IExternalDataComponent * pExternalDataComponent = pInstance->GetExternalDataComponent())
    {
        IExternalData *pData = pExternalDataComponent->FindExternalData(StructureSlantedColumn::GetStaticClassSchema()->GetName());
        DBG_WARN_AND_RETURN_UNLESS(pData, nullptr, L"结构构件应该会有ExternalData",L"GDMPLab",L"2024-03-30");
        return quick_cast<StructureSlantedColumn>(pData);
    }
    return nullptr;
}


IInstance* StructureSlantedColumn::CreateSlantedColumn(const StructureColumnInput* pInput)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInput, L"pInput为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(!pInput->IsVerticalColumn, L"pInput 创建参数有误",L"GDMPLab",L"2024-03-30");

    IDocument* pDoc = pInput->Document;
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    ElementId associatedPlaneId = pInput->AssociatedPlaneId;
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(associatedPlaneId.IsValid(), L"associatedPlaneId无效",L"GDMPLab",L"2024-03-30");
    ElementId topAssociatedPlaneId = pInput->TopAssociatedPlaneId;

    //todo:去除依赖PointArrayPlusHeight方式创建Instance
    IInstanceType* pInstanceType = quick_cast<IInstanceType> (pDoc->GetElement(pInput->InstanceTypeId));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInstanceType, L"pInstanceType无效",L"GDMPLab",L"2024-03-30");

    IElementBasicInformation* pIfmt = pInstanceType->GetBasicInformation();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pIfmt, L"pIfmt无效",L"GDMPLab",L"2024-03-30");
 
    std::wstring instanceTypeName = pIfmt->GetName();

    OwnerPtr<IPointArrayInstanceInput> opInputArray = IPointArrayInstanceInput::Create(pDoc,
        pInput->AssociatedPlaneId, pInput->FamilyId, instanceTypeName, pInput->PositionPoints);

    opInputArray->SetCanBeShared(pInput->CanBeShared);
    opInputArray->SetCreationOption(pInput->CreationOption);
    opInputArray->SetHeight(pInput->Height);

    // 创建实例
    IInstance *pInstance = IInstance::CreateByPointArray(opInputArray.get(), false);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInstance, L"构件创建失败",L"GDMPLab",L"2024-03-30");

    //挂externalData
    IStructureSlantedColumn* pSlantedColumn = StructureSlantedColumn::RegisterExternalData(pInstance, pInput);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSlantedColumn, L"pSlantedColumn为空",L"GDMPLab",L"2024-03-30");

    //设置instance的Unidentity
    if (pInput->categoryUid.IsValid())
    {
        pInstance->GetBasicInformation()->SetCategoryUid(pInput->categoryUid);
    }

    // 设置定位件
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInput->PositionPoints.size() == 2, L"PositionPoints非法",L"GDMPLab",L"2024-03-30");
    IElementPosition::CreateCurve2dOnTwoAssociatedPlanesPositionBehavior(pInstance
        , associatedPlaneId, pInput->AssociatedPlaneOffset, pInput->PositionPoints, topAssociatedPlaneId, pInput->TopOffset);

    //当顶部标高为无效值时，高度取设置的高度，为有效值时，取上下标高差值(注：差值应包含偏移)
    IElementPosition *posBehavior = pInstance->GetElementPosition();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(posBehavior != nullptr, L"无效posBehavior",L"GDMPLab",L"2024-03-30");
    const IPositionTwoAssociatedPlanes *pTwoAssociatedPlane = dynamic_cast<const IPositionTwoAssociatedPlanes *>(posBehavior->GetPositionAssociatedPlane());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pTwoAssociatedPlane, L"无法读取高度参数",L"GDMPLab",L"2024-03-30");
    double height = ElementId::InvalidID == pTwoAssociatedPlane->GetTopAssociatedPlaneId()? pInput->Height: pTwoAssociatedPlane->ComputeHeight();

    IElementParameters *pParamBehavior = pInstance->GetElementParameters();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pParamBehavior, L"ParamBehavior为空",L"GDMPLab",L"2024-03-30");
    {
        //设置高度值
        OwnerPtr<IParameter> heightParam = pParamBehavior->GetParameterByUid(PARAMETER_UID(ColumnHeightBuiltInParameter));
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(IParameter::IsValidParameter(heightParam), L"没有高度参数",L"GDMPLab",L"2024-03-30");
        heightParam->SetValueAsDouble(height);
        bool bOK = pParamBehavior->SetParameter(heightParam.get());
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOK, L"高度设置失败",L"GDMPLab",L"2024-03-30");
    }

    //设置截面旋转角度
    OwnerPtr<IParameter> angleParam = 
        pParamBehavior->GetParameterByUid(PARAMETER_UID(SectionRotateAngleBuiltInParameter));
    if (IParameter::IsValidParameter(angleParam))
    {
        angleParam->SetValueAsDouble(pInput->RotateAngle);
        bool bOK = pParamBehavior->SetParameter(angleParam.get());
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOK, L"角度设置失败",L"GDMPLab",L"2024-03-30");
    }

    //添加参数更新器
    IElementPosition* pPosBehavior = pInstance->GetElementPosition();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pPosBehavior, L"无效pPositionBehavior",L"GDMPLab",L"2024-03-30");
    OwnerPtr<IInstanceFamilyParametersUpdater> opParametersUpdater = NEW_AS_OWNER_PTR(StructureColumnHeightParameterUpdater);
    pPosBehavior->SetParametersUpdater(TransferOwnership(opParametersUpdater));

    //设置所属楼层
    if (pInput->StoreyId.IsValid())
    {
        bool bOk = StructureInstanceLevelUtils::CreateInstanceStoreyLevel(pDoc, pInstance->GetElementId(), pInput->StoreyId);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"SetStoreyLevel失败",L"GDMPLab",L"2024-03-30");
    }
    else
    {
        const ILevel* pStoreyLevel = StructureInstanceLevelUtils::GetColumnStoreyLevelFromPositioningLevel(pDoc, associatedPlaneId);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pStoreyLevel, L"pStoreyLevel为空",L"GDMPLab",L"2024-03-30");
        bool bOk = StructureInstanceLevelUtils::CreateInstanceStoreyLevel(pInstance, pStoreyLevel);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"SetStoreyLevel失败",L"GDMPLab",L"2024-03-30");
    }

    //属性面板行为
    if (pInstance->GetElementParameters())
    {
        OwnerPtr<IElementParametersCustomizer> opNewCustomizer = 
            NEW_AS_OWNER_PTR(StructureSlantedColumnElementParametersCustomizer, pInstance);
        GmStructureDefaultElementParametersCustomizer::SetElementParametersCustomizer(
            pInstance, TransferOwnership(opNewCustomizer));
    }

    //截面行为
    OwnerPtr<StructureColumnEndTypeBehavior> opInstanceEndTypeBehavior = NEW_AS_OWNER_PTR(StructureColumnEndTypeBehavior, pInstance);
    pInstance->AddGraphicsElementShapeCustomizableBehavior(TransferOwnership(opInstanceEndTypeBehavior));

    //倾斜角度行为
    IElementParameters * pElementParameters = pInstance->GetElementParameters();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pElementParameters, L"pInstance的参数行为为空？",L"GDMPLab",L"2024-03-30");
    pElementParameters->AddIndividualParameterOverride(NEW_AS_OWNER_PTR(NotModifiableColumnAngleBuiltInParameterOverride));
    pElementParameters->AddIndividualParameterOverride(NEW_AS_OWNER_PTR(GeneralHeightBuiltInParameterOverride, pInstance, PARAMETER_UID(ColumnHeightBuiltInParameter)));

    //可见性
    IElementStatus* pStatus = pInstance->GetStatus();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pStatus, L"无法获取状态集",L"GDMPLab",L"2024-03-30");
    pStatus->SetIsVisible(pInput->Visible);

    bool bOk = pDoc->GetRegenerator()->RegenerateElement(pInstance->GetElementId());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"RegenerateElement失败",L"GDMPLab",L"2024-03-30");

    return pInstance;
}
IStructureSlantedColumn* StructureSlantedColumn::RegisterExternalData(IInstance* pInstance, const StructureColumnInput* pInput)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInstance, L"pInstance为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInput, L"pInput为空",L"GDMPLab",L"2024-03-30");

    OwnerPtr<StructureSlantedColumn> opSlantedColumn = NEW_AS_OWNER_PTR(StructureSlantedColumn);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opSlantedColumn, L"opSlantedColumn为空",L"GDMPLab",L"2024-03-30");

    OwnerPtr<StructureColumn> opBaseData = StructureColumn::Create(pInstance, pInput);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opBaseData, L"opBaseData为空",L"GDMPLab",L"2024-03-30");
    opSlantedColumn->SetBaseData__(TransferOwnership(opBaseData));

    opSlantedColumn->SetTopSectionType(pInput->TopFaceEndType);
    opSlantedColumn->SetBottomSectionType(pInput->BottomFaceEndType);

    StructureSlantedColumn* pSlantedColumn = opSlantedColumn.get();
    if (IExternalDataComponent * pExternalDataComponent = pInstance->GetExternalDataComponent())
    {
        pExternalDataComponent->RegisterExternalData(StructureSlantedColumn::GetStaticClassSchema()->GetName(), TransferOwnership(opSlantedColumn));
    }
    return pSlantedColumn;
}

void StructureSlantedColumn::UpdateForWeakParentDeletion(const std::set<ElementId>& deletedElementIds)
{
    GetBaseDataFW__()->UpdateForWeakParentDeletion(deletedElementIds);
}

void StructureSlantedColumn::ReportParents(IElementParentReporter& reporter) const
{
    GetBaseData__()->ReportParents(reporter);
}

void StructureSlantedColumn::GetCalculators(ICalculatorCollection * calculators) const
{
    GetBaseData__()->GetCalculators(calculators);
    const IElement *pElement = GetOwnerElement();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElement, L"pElement为空",L"GDMPLab",L"2024-03-30");

    const IElementParameters* pElementParameters = pElement->GetElementParameters();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElementParameters, L"参数行为为空",L"GDMPLab",L"2024-03-30");

    ADD_CALCULATOR_OVERRIDE_REGENDATA(SlantedColumnAngleCalculator, GetDocument(), pElementParameters->GetCoordinateSystemParameterRdId());
}

void StructureSlantedColumn::ReportParameterDefinitions(std::vector<int>* pParamDefIds) const
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pParamDefIds != nullptr, L"pParamDefUids为空",L"GDMPLab",L"2024-03-30");
    GetBaseData__()->ReportParameterDefinitions(pParamDefIds);

    pParamDefIds->push_back(PARAMETER_ID(ColumnTopSectionType));
    pParamDefIds->push_back(PARAMETER_ID(ColumnBottomSectionType));
}

OwnerPtr<IParameter> StructureSlantedColumn::GetNativeParameter(int paramDefId) const
{
    OwnerPtr<IParameter> ret = GetBaseData__()->GetNativeParameter(paramDefId);
    if (IParameter::IsValidParameter(ret))
    {
        return ret;
    }

    OwnerPtr<IParameter> param;
    ParameterAttributes pa = {false, false, true};
    if (paramDefId == PARAMETER_ID(ColumnTopSectionType))
    {
        //param = NEW_AS_OWNER_PTR(Parameter, GetDocument(), ParameterStorageType::Int, false, false,
            //true, PARAMETER_UID(ColumnTopSectionType), ParameterProcessType::GeneralInput);
        param = IParameter::CreateParameter(GetDocument(), ParameterStorageType::Int, pa,
            PARAMETER_UID(ColumnTopSectionType), ParameterProcessType::GeneralInput);
        param->SetValueAsInt((int32_t)GetTopSectionType__());
        return TransferOwnership(param);
    }
    else if (paramDefId == PARAMETER_ID(ColumnBottomSectionType))
    {
        //param = NEW_AS_OWNER_PTR(Parameter, GetDocument(), ParameterStorageType::Int, false, false,
            //true, PARAMETER_UID(ColumnBottomSectionType), ParameterProcessType::GeneralInput);
        param = IParameter::CreateParameter(GetDocument(), ParameterStorageType::Int, pa,
            PARAMETER_UID(ColumnBottomSectionType), ParameterProcessType::GeneralInput);
        param->SetValueAsInt((int32_t)GetBottomSectionType__());
        return TransferOwnership(param);
    }
    return nullptr;
}

bool StructureSlantedColumn::SetNativeParameter(const IParameter *param, std::wstring* errorMsg/* = nullptr*/)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(param, L"param is null.",L"GDMPLab",L"2024-03-30");

    bool bOk = GetBaseDataFW__()->SetNativeParameter(param, errorMsg);
    if (bOk)
    {
        return true;
    }

    if (param->GetParameterDefinitionId() == PARAMETER_ID(ColumnTopSectionType))
    {
        SetTopSectionType((InstanceEndType)param->GetValueAsInt());
        return true;
    }
    else if (param->GetParameterDefinitionId() == PARAMETER_ID(ColumnBottomSectionType))
    {
        SetBottomSectionType((InstanceEndType)param->GetValueAsInt());
        return true;
    }

    return false;
}

bool StructureSlantedColumn::IsParameterModifiable(int paramDefId) const
{
    if (paramDefId == PARAMETER_ID(ColumnTopSectionType) || 
        paramDefId == PARAMETER_ID(ColumnBottomSectionType))
    {
        return true;
    }

    return GetBaseData__()->IsParameterModifiable(paramDefId);
}

void StructureSlantedColumn::Report(const gcmp::ICopyContext & copyContext, gcmp::ICopyStrategyReporter& reporter) const
{
    GetBaseData__()->Report(copyContext, reporter);
}

double StructureSlantedColumn::GetVolume() const
{
    return GetBaseData__()->GetVolume();
}

double StructureSlantedColumn::GetHeight() const
{
    return GetBaseData__()->GetHeight();
}

void StructureSlantedColumn::SetTopSectionType(InstanceEndType sectionType)
{
    SetTopSectionType__(sectionType);
    MarkTopSectionTypeRdId();
}

void StructureSlantedColumn::SetBottomSectionType(InstanceEndType sectionType)
{
    SetBottomSectionType__(sectionType);
    MarkBottomSectionTypeRdId();
}

bool StructureSlantedColumn::SetOwnerElement(IElement* pOwnerElement)
{
    return m_BaseData->SetOwnerElement(pOwnerElement);
}
IElement* StructureSlantedColumn::GetOwnerElement()
{
    return GetBaseDataFW__()->GetOwnerElement();
}
const IElement* StructureSlantedColumn::GetOwnerElement() const
{
    return GetBaseData__()->GetOwnerElement();
}

IDocument * StructureSlantedColumn::GetDocument() const
{
    return GetBaseData__()->GetDocument();
}

ElementId StructureSlantedColumn::GetOwnerElementId() const
{
    return GetBaseData__()->GetElementId();
}

gcmp::NdbObject* StructureSlantedColumn::GetTopOwnerObject() const
{
    const StructureColumn* pBaseData = GetBaseData__().get();
    if (!pBaseData)
        return nullptr;
    return pBaseData->GetTopOwnerObject();
}
